package com.boss.salary.service.impl;

import com.boss.common.service.ICommonService;
import com.boss.common.util.DateUtils;
import com.boss.salary.dao.IAgencySalaryPaymentDao;
import com.boss.salary.dao.IGenerateSalaryDataDao;
import com.boss.salary.dao.IPayMentLockDao;
import com.boss.salary.dao.ISalaryWarnMonthDao;
import com.boss.salary.entity.AgencyInfo;
import com.boss.salary.entity.AgencySalaryPayment;
import com.boss.salary.entity.PaymentMassage;
import com.boss.salary.entity.SalaryWarnMonth;
import com.boss.salary.service.IAgencyInfoService;
import com.boss.salary.service.ISalaryWarnMonthService;
import com.boss.sys.ca.user.dto.UserDTO;
import com.boss.sys.utils.SysUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SalaryWarnMonthServiceImpl implements ISalaryWarnMonthService {

    /**
     * 引入日志框架常量
     */
    private final static Logger logger = LoggerFactory.getLogger(SalaryWarnMonthServiceImpl.class);

    @Autowired
    private ISalaryWarnMonthDao iSalaryWarnMonthDao;
    @Autowired
    private IAgencyInfoService iAgencyInfoService;
    @Autowired
    private IGenerateSalaryDataDao iGenerateSalaryDataDao;
    @Autowired
    private IPayMentLockDao iPayMentLockDao;
    @Autowired
    private IAgencySalaryPaymentDao iAgencySalaryPaymentDao;
    @Autowired
    private ICommonService iCommonService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSalaryWarnMonth(SalaryWarnMonth salaryWarnMonth,UserDTO userDTO) {
        if(StringUtils.isEmpty(salaryWarnMonth.getId())){
            salaryWarnMonth.setId(SysUtils.generateGuid());
        }
        salaryWarnMonth.setCreateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        salaryWarnMonth.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        iSalaryWarnMonthDao.updateSalaryWarnMonth(salaryWarnMonth,userDTO);
    }

    @Override
    public SalaryWarnMonth getSalaryWarnMonth(String province) {
        return iSalaryWarnMonthDao.getSalaryWarnMonth(province);
    }

    /**
     * 检测指标是否满足月份
     * @param salaryWarnMonth
     * @param userDto
     * @return
     */
    @Override
    public Map<String, Object> checkWarnMonthLoading(SalaryWarnMonth salaryWarnMonth, UserDTO userDto,String tokenid) {
        //获取全部单位信息
        List<AgencyInfo> agencyInfos = iAgencyInfoService.getAllAgency(userDto);
        List<String> agencyInfoId= new ArrayList();
        for(AgencyInfo agencyId:agencyInfos){
            agencyInfoId.add(agencyId.getId());
        }
        Map<String, Object> requestList=new HashMap<>();
        List<Map<String, Object>> falsePayList=new ArrayList<>();
        List<String> agencyIds=new ArrayList<>();
        //校验指标是否单位是否挂接指标和收款户
        StringBuffer request=new StringBuffer();
        logger.info("提前校验：校验指标挂接情况开始");
        StringBuffer result=new StringBuffer();
        //校验单位是否所有人员类型都挂接了指标工资项收款户
        List<Map<String,Object>> rSalayPersonTypeList=iGenerateSalaryDataDao.isSalaryAllConnectPersonType(agencyInfoId);
        if(!CollectionUtils.isEmpty(rSalayPersonTypeList)){
            for(Map<String,Object> rmap:rSalayPersonTypeList){
                result.append(rmap.get("agency_name")).append(":").append(rmap.get("person_type"))
                        .append(" 银行编码：").append(rmap.get("bank")).append(" 未挂接指标工资项收款户<br/>");
                agencyInfoId.remove(rmap.get("id"));
                agencyIds.add(rmap.get("id").toString());
            }
        }
        List<Map<String,Object>> rmapList=iGenerateSalaryDataDao.isPaymentAllConnectPersonType(agencyInfoId);
        if(!CollectionUtils.isEmpty(rmapList)){
            for(Map<String,Object> rmap:rmapList){
                result.append(rmap.get("agency_name")).append(":").append(rmap.get("person_type")).append("-")
                        .append(rmap.get("salary_base_name")).append(" 收款户：").append(rmap.get("bank")).append(" 未挂接指标<br/>");
                agencyInfoId.remove(rmap.get("id"));
                agencyIds.add(rmap.get("id").toString());
            }
        }



        // 获取已冻结的推送给支付的数据
        logger.info("提前校验：获取指标冻结信息开始");
        List<Map<String, Object>> budgetThawpayList=iPayMentLockDao.selectPayMentLock(agencyInfoId);
        //若获取到锁定指标则批量解冻
        //不需要删除冻结的id
//        if(!CollectionUtils.isEmpty(budgetThawpayList)) {
//            for (Map<String, Object> map : budgetThawpayList) {
//                //则将获取到的已锁定单位从List中移除
//                agencyInfoId.remove(map.get("agency_id"));
//            }
//        }
        List<Map<String, Object>>  payList=new ArrayList<>();
        //检查指标是否足够
        if(!CollectionUtils.isEmpty(agencyInfoId)) {
            logger.info("提前校验：校验指标是否充足");
            falsePayList = checkIsEnough(agencyInfoId, userDto, payList,false,salaryWarnMonth,budgetThawpayList,tokenid);
        }
        if(!CollectionUtils.isEmpty(falsePayList)) {
            for (Map reMap : falsePayList) {
                request.append(reMap.get("agency_name").toString() + reMap.get("merit_name").toString() + reMap.get("salary_name").toString() + "指标余额不足！<br/>");
                agencyIds.add(reMap.get("agency_id").toString());
            }
        }
        requestList.put("request",request.toString());
        requestList.put("data",agencyIds);

        return requestList;
    }

    @Override
    public List<Map<String, Object>> checkIsEnough(List<String> agencyIds, UserDTO userDto, List<Map<String, Object>> payRequestList, boolean is_agency, SalaryWarnMonth salaryWarnMonth,List<Map<String, Object>> budgetThawpayList,String tokenid) {
        //获取所有该区划下挂接指标的工资项
        List<String> columnList = iGenerateSalaryDataDao.getPayeeColumnName(userDto.getProvince());
        // 获取不同人员类型的工资数据
        //agency_id  agency_code agency_name state merit_pay_code sala_card_bank  s...
        //List<Map<String, Object>> salaryList = iGenerateSalaryDataDao.getPersonOtherSalary(agencyIds, columnList,is_agency);
        List<Map<String, Object>> salaryList = iGenerateSalaryDataDao.getPersonOtherSalarys(agencyIds, columnList,is_agency,salaryWarnMonth);

        // 获取收款户对应的字段
        // column_name salary_base_id person_state agency_id payee_acct_name payee_acct_no payee_acct_bank_name remark
        List<Map<String, Object>> payeeColumnList = iGenerateSalaryDataDao.getPayeeColumnName(agencyIds);
        //获取所有单位挂接指标情况
        List<AgencySalaryPayment> agencyBgtLists = iAgencySalaryPaymentDao.getBgtBySalaryPersonType(agencyIds,userDto);
        //获取所有挂接的指标，查询指标余额用
        List<String> sumIds=agencyBgtLists.stream().map(e -> e.getBgtId()).distinct().collect(Collectors.toList());
        //获取指标可用额度
        //bgtid 1需要和冻结指标做加法处理
        PaymentMassage paymentMassage=iCommonService.getPayMent(sumIds, userDto,tokenid);

        Map<String, BigDecimal> bgtCanuse=  paymentMassage.getBgtCanuse();
        if(budgetThawpayList.size()>0&&null!=budgetThawpayList){
            for(Map map1: budgetThawpayList){
                for(String key :bgtCanuse.keySet()) {
                    if (map1.get("bgt_id").equals(key)){
                        BigDecimal a=bgtCanuse.get(key);
                        BigDecimal b= (BigDecimal) map1.get("amt");
                        BigDecimal c=a.add(b);
                        bgtCanuse.put(key,c);

                    }
                }
            }
        }
        //获取工资类型map code-name
        Map<String, Object>  meritMap=iCommonService.queryBaseDataMap("salary_type",userDto.getProvince());
        //获取工资项id-name Map
        Map<String, Object>  salaryBaseMap=iCommonService.querySalaryBaseDataMap(userDto.getProvince());
        //todo
        //保存各单位各收款户金额
        List<Map<String,Object>> moneyMapList=new ArrayList<>();
        if (!StringUtils.isEmpty(salaryList) && salaryList.size() > 0) {
            // 指标额度是否足够
            for (Map<String, Object> map : salaryList) {
                // 工资类型
                String meritPayCode = map.get("merit_pay_code").toString();
                // 根据单位id和人员类别获取工资项和金额
                for (Map<String, Object> payeeMap: payeeColumnList) {
                    if (map.get("agency_id").equals(payeeMap.get("agency_id")) &&
                            meritPayCode.equals(payeeMap.get("person_state"))) {
                        String salaryId = payeeMap.get("salary_base_id").toString();
                        String bankCode = map.get("agency_id") + "-" + salaryId  + "-" + meritPayCode;
                        String column = payeeMap.get("column_name").toString();
                        String payee_acct_name=payeeMap.get("payee_acct_name").toString();//收款户名称
                        String payee_acct_no=payeeMap.get("payee_acct_no").toString();//收款户账号
                        String payee_acct_bank_name=payeeMap.get("payee_acct_bank_name").toString();//收款户银行
                        Object use_=payeeMap.get("remark");//资金用途
                        BigDecimal amt = BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(map.get(column)) ? "0.00" : map.get(column).toString()));
                        if(amt.doubleValue()<=0){
                            continue ;
                        }
                        Map<String,Object> money=new HashMap<>();
                        money.put("agency_id",map.get("agency_id"));
                        money.put("agency_name",map.get("agency_name"));
                        money.put("merit_name",meritMap.get(meritPayCode));//工资类型名称
                        money.put("salary_name",salaryBaseMap.get(salaryId));//工资项名称
                        money.put("bankCode",bankCode);//键值用单位id 工资项id 和人员工资类型混合键
                        money.put("payee_acct_name",payee_acct_name);
                        money.put("payee_acct_no",payee_acct_no);
                        money.put("payee_acct_bank_name",payee_acct_bank_name);
                        money.put("amt",amt.toString());
                        money.put("use_",use_);
                        moneyMapList.add(money);
                    }
                }
            }
        }
        //todo 计算指标额度是否足够
        List<Map<String,Object>> payList=new ArrayList<>();
        for(Map moneyMap:moneyMapList){
            for(AgencySalaryPayment agencySalaryPayment:agencyBgtLists){
                if(moneyMap.get("bankCode").equals( agencySalaryPayment.getAgencyId() + "-" + agencySalaryPayment.getSalaryId()  + "-" + agencySalaryPayment.getPersonType())){
                    BigDecimal canuse=bgtCanuse.get(agencySalaryPayment.getBgtId());
                    if(canuse==null){
                        continue;
                    }
                    BigDecimal amt=new BigDecimal(moneyMap.get("amt").toString());
                    if(amt.compareTo(new BigDecimal("0.00"))==0){
                        continue;
                    }
                    if(amt.compareTo(canuse) != 1){//如果可用额度大于申请额度
                        bgtCanuse.put(agencySalaryPayment.getBgtId(),canuse.subtract(amt));//指标额度扣减
                        moneyMap.put("amt","0");
                        Map<String,Object> payMap=new HashMap<>();
                        payMap.put("agency_id",moneyMap.get("agency_id"));
                        //payMap.put("bankCode",moneyMap.get("bankCode"));//键值用单位id 工资项id 和人员工资类型混合键
                        payMap.put("bgt_id",agencySalaryPayment.getBgtId());
                        payMap.put("payee_acct_name",moneyMap.get("payee_acct_name"));
                        payMap.put("payee_acct_no",moneyMap.get("payee_acct_no"));
                        payMap.put("payee_acct_bank_name",moneyMap.get("payee_acct_bank_name"));
                        payMap.put("amt",amt);
                        payMap.put("use_",moneyMap.get("use_"));
                        payList.add(payMap);
                    }else{
                        if(canuse.compareTo(new BigDecimal("0.00"))==0){
                            continue;
                        }
                        bgtCanuse.put(agencySalaryPayment.getBgtId(),new BigDecimal("0.00"));//指标额度扣减
                        moneyMap.put("amt",amt.subtract(canuse));
                        Map<String,Object> payMap=new HashMap<>();
                        payMap.put("agency_id",moneyMap.get("agency_id"));
                        //payMap.put("bankCode",moneyMap.get("bankCode"));//键值用单位id 工资项id 和人员工资类型混合键
                        payMap.put("bgt_id",agencySalaryPayment.getBgtId());
                        payMap.put("payee_acct_name",moneyMap.get("payee_acct_name"));
                        payMap.put("payee_acct_no",moneyMap.get("payee_acct_no"));
                        payMap.put("payee_acct_bank_name",moneyMap.get("payee_acct_bank_name"));
                        payMap.put("amt",canuse);
                        payMap.put("use_",moneyMap.get("use_"));
                        payList.add(payMap);
                    }
                }
            }

        }
        List<Map<String,Object>> falseRemovePayList=new ArrayList<>();
        List<Map<String,Object>> falsePayList=new ArrayList<>();
        for(Map moneyMap:moneyMapList){//将原集合中还有金额不为0的过滤出来，不为零表明指标不足
            if(!"0".equals(moneyMap.get("amt"))){//将指标不足的单位从成功集合中剔除
                falseRemovePayList.addAll(payList.stream().filter(map -> moneyMap.get("agency_id").equals(map.get("agency_id"))).collect(Collectors.toList()));
                falsePayList.add(moneyMap);
                agencyIds.remove(moneyMap.get("agency_id"));
            }
        }
        payList.removeAll(falseRemovePayList);//将指标不足的单位从成功集合中剔除
        payRequestList.addAll(payList);//所有成功的添加到传入的List集合中
        return falsePayList;//返回所有失败的信息
    }
}
